import { Injectable } from '@nestjs/common';
import { InjectEntityManager } from '@nestjs/typeorm';
import { Booking } from 'src/booking/entities/booking.entity';
import { MeetingRoom } from 'src/meeting-room/entities/meeting-room.entity';
import { User } from 'src/user/entities/user.entity';
import { EntityManager } from 'typeorm';

@Injectable()
export class StatisticService {
  @InjectEntityManager()
  private entityManager: EntityManager;

  /**
   * 统计用户的预定次数
   * @param startTime
   * @param endTime
   * @returns
   */
  async userBookingCount(startTime: string, endTime: string) {
    const res = await this.entityManager
      .createQueryBuilder(Booking, 'b') // createQueryBuilder 创建一个 QueryBuilder 来查询 Booking 实体。 b 是 Booking 实体的一个别名，后面查询语句中用 b 代表 Booking 表
      .select('u.id', 'userId') // 选择 User 表的 id 字段，并将结果命名为 用户id
      .addSelect('u.username', 'username') // 选择 User 表的 username 字段，并将结果命名为 用户名
      .leftJoin(User, 'u', 'b.userId = u.id') // 使用 leftJoin 关联 User 表，即对 Booking 表中的 userId 和 User 表中的 id 进行左连接。
      .addSelect('count(1)', 'bookingCount')
      .where('b.startTime between :time1 and :time2', {
        time1: startTime,
        time2: endTime,
      })
      .addGroupBy('b.user')
      .getRawMany(); // 执行查询并返回原始的查询结果，即数据库返回的数据不会被 TypeORM 映射为实体类，而是直接作为原始数据返回。结果会是一个数组，每个元素对应一个用户的预定次数。

    return res;
  }

  /**
   * 统计会议室的使用次数
   */
  async meetingRoomUsedCount(startTime:string,endTime:string) {
    const res = await this.entityManager
      .createQueryBuilder(Booking, 'b')
      .select('m.id', 'meetingRoomId')
      .addSelect('m.name', 'meetingRoomName')
      .leftJoin(MeetingRoom, 'm', 'b.roomId = m.id')
      .addSelect('count(1)', 'usedCount')
      .where('b.startTime between :time1 and :time2', {
        time1: startTime,
        time2: endTime
      })
      .addGroupBy('b.roomId')
      .getRawMany()

      return res
  }
}
/**
 * 关于 createQueryBuilder 的使用
 * .createQueryBuilder(Booking, 'b') 创建一个 QueryBuilder 来查询 Booking 实体。 b 是 Booking 实体的一个别名，后面查询语句中用 b 代表 Booking 表
 * .select('u.id', '用户id') 选择 User 表的 id 字段，并将结果命名为 用户id
 * .addSelect('u.username', '用户名') // 选择 User 表的 username 字段，并将结果命名为 用户名
 * select 和 addSelect 的区别：
 *  select() 用于指定查询中的初始选择字段，如果不使用select() 默认会选择所有列
 *  addSelect() 用于追加选择字段。如果已经使用了 select()，可以使用 addSelect() 来添加更多的字段，而不覆盖之前的 select() 的选择
 *  addSelect() 常用于在已有查询字段的基础上再动态添加一些字段
 *
 * leftJoin() 是 TypeORM 中 QueryBuilder 的一种关联查询方法，主要用于在执行查询时将两个实体表连接起来。
 * leftJoin() 是左连接，即即使关联表没有匹配的数据，主表的数据也会出现在查询结果中，并且未匹配的部分用 null 填充
 * leftJoin(entity: Function | string, alias: string, condition?: string, parameters?: Object)
 *  entity: 关联的实体（表）。它可以是一个实体类（如 User）或者表名的字符串。
    alias: 给关联表指定的别名，用于在查询中引用这个表。
    condition: 可选的连接条件，定义如何将主表的字段与关联表的字段匹配。
    parameters: 可选的参数，用于防止 SQL 注入，并让查询更动态和灵活。
 */
